home *** CD-ROM | disk | FTP | other *** search
- /* -*- C -*-
- * RULES.C
- *
- * (c)Copyright 1991-93 by Tobias Ferber, All Rights Reserved
- */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- #include "cvt.h"
-
-
- /*** / GLOBALS / ***/
-
- crule_t **crules; /* global crule_t * array of size global_numrules */
-
- int global_numrules= 0; /* total #of rules; counted by readcrule() */
-
- int global_maxlhs= 0; /* current maximum length of a lhs in 'crules'.
- * This value is updated with each call of
- * addcrule() */
-
-
- /*** / NEW / ***/
-
- crule_t *new(void)
- /* allokiert eine neue crule und initialisiert die members */
- { crule_t *rp= (crule_t *)malloc(sizeof(crule_t));
- if(rp)
- { rp->next= NIL(crule_t);
- rp->lhs= rp->rhs= (char *)0L;
- rp->l= rp->r= 0;
- rp->ln= 0;
- }
- return rp;
- }
-
-
- /*** / DISPOSE / ***/
-
- crule_t *dispose(crule_t *rp)
- /* gibt eine crule frei und ihren Nachfolger zur"uck */
- { crule_t *succ= rp->next;
- if(rp->lhs) { free(rp->lhs); rp->lhs= (char *)0L; rp->l= 0; }
- if(rp->rhs) { free(rp->rhs); rp->rhs= (char *)0L; rp->r= 0; }
- rp->ln= 0;
- free(rp);
- return succ;
- }
-
-
- /*** / INIT_RULES / ***/
-
- int init_rules(void)
- /* richtet das 'crules' array ein und initialisiert es auf NIL(crule_t).
- * Es wird hier nicht "uberpr"uft ob die ANSI Grenze von 64k f"ur
- * malloc() "uberschritten wird, was aber auch "au\3erst unwahrscheinlich
- * ist. */
- {
- #ifdef DEBUG
- if(debuglevel >= 1)
- printf("> init_rules() entered to malloc() %ld bytes of memory\n",
- global_numchars * sizeof(crule_t *));
- #endif
-
- crules= (crule_t **)malloc(global_numchars * sizeof(crule_t *));
-
- if(crules)
- { long i;
- for(i=0; i<global_numchars; i++)
- crules[i]= NIL(crule_t);
- return 0;
- }
- else return 1;
- }
-
-
- /*** / EXIT_RULES / ***/
-
- void exit_rules(void)
- /* Hier werden alle Eintr"age in 'crules' aufgel"ost und deren Speicher
- * freigegeben. Au\3erdem wird 'crules' selbst abgebaut. */
- {
- #ifdef DEBUG
- if(debuglevel >= 1)
- printf("> exit_rules() entered to free() %ld rules for %ld chars\n",
- global_numrules, global_numchars);
- #endif
-
- if(crules)
- { long i;
- for(i=0; i<global_numchars; i++)
- { crule_t *rp= crules[i];
- while(rp) rp= dispose(rp);
- crules[i]= NIL(crule_t);
- }
- free(crules);
- }
- global_numrules= 0;
- }
-
-
- /*** / ADDCRULE / ***/
-
- int addcrule(crule_t *rp)
- /* Hier wird eine crule 'rp' in das globale 'crules' array eingef"ugt.
- * Der erste Buchstabe der lhs von 'rp' bestimmt den index in 'crules'.
- * Wenn dort schon ein Eintrag ist, wird 'rp' so eingesetzt, da\3 jeder
- * Vorg"anger von 'rp' eine l"angere lhs hat und jeder Nachfolger eine
- * k"urzere. Bei gleicher L"ange wird nach den ASCII Werten in lhs
- * absteigend sortiert, d.h. Vorg"anger haben gr"o\3ere ASCII Werte
- * als die Nachfolger.
- * Der R"uckgabewert ist 0 wenn alles geklappt hat, 1, wenn die gleiche
- * lhs schon vorhanden war und 2, wenn 'rp' oder dessen lhs leer war. */
- { if(rp && rp->lhs)
- { int r= (int)((rp->lhs)[0] & 0377);
- crule_t *m= NIL(crule_t), *n= crules[r];
- while(n && n->l > rp->l) { m=n; n=n->next; }
- if(n && n->l == rp->l)
- { char *s= n->lhs, *t= rp->lhs;
- int l= n->l; /* == rp->l */
- while(l-- && *s==*t) { ++s; ++t; }
- if(l<0) return 1; /* ambiguous! */
- else if(*s>*t) m=n;
- }
- if(m) { rp->next=m->next; m->next=rp; }
- else { rp->next= crules[r]; crules[r]= rp; }
- if(rp->l > global_maxlhs) global_maxlhs= rp->l;
- return 0;
- }
- return 2;
- }
-
-
- #ifdef DEBUG
-
- /*** / MAXLHS / ***/
-
- int maxlhs(void)
- /* Ermittelt den l"angsten linken Kontext in 'crules' */
- { int r, m=0;
- for(r=0; r<global_numchars; r++)
- { crule_t *rp= crules[r];
- while(rp)
- { if(rp->l > m) m= rp->l;
- rp= rp->next;
- }
- }
- return m;
- }
-
-
- /*** / PRINT_CRULE / ***/
-
- void print_crule(crule_t *rp)
- {
- if(rp->l && rp->lhs)
- { int i,q;
- for(i=q=0; i<rp->l; i++)
- { int c= (rp->lhs)[i]&0xFF;
- if(isprint(c))
- { if(!q)
- { putchar('\"');
- q=1;
- }
- if(c=='\\' || c=='\"')
- putchar('\\');
- putchar(c);
- }
- else /* !isprint(c) */
- { if(q)
- { printf("\",");
- q=0;
- }
- printf("$%02x",c);
- }
- if(rp->l>i+1 && q==0)
- putchar(',');
- }
- if(q) putchar('\"');
- printf("->");
- if(rp->r && rp->rhs)
- { for(i=q=0; i<rp->r; i++)
- { int c= (rp->rhs)[i]&0xFF;
- if(isprint(c))
- { if(!q)
- { putchar('\"');
- q=1;
- }
- if(c=='\\' || c=='\"')
- putchar('\\');
- putchar(c);
-
- }
- else /* !isprint(c) */
- { if(q)
- { printf("\",");
- q=0;
- }
- printf("$%02x",c);
- }
- if(rp->r>i+1 && q==0)
- putchar(',');
- }
- if(q) putchar('\"');
- }
- printf("; // line %d\n",rp->ln);
- }
- else printf("// empty rule in line %d\n",rp->ln);
- }
-
-
- /*** / DUMP_CRULES / ***/
-
- void dump_crules(void)
- /* prints all rules in 'crules' */
- { crule_t *rp;
- int r;
- printf("/*** / CONVERSION RULES / ***/\n");
- for(r=0; r<global_numchars; r++)
- { rp= crules[r];
- while(rp)
- { print_crule(rp);
- rp= rp->next;
- }
- }
- printf("// %d rules; maximum lhs is %d\n",global_numrules, maxlhs());
- }
-
- #endif /* DEBUG */
-